/**
 * 2009-12-14，新增store中文排序
 * @type {}
 */
Ext.data.Store.prototype.applySort=function(){
	if(this.sortInfo&&!this.remoteSort){
		var s=this.sortInfo,f=s.field;
		var st=this.fields.get(f).sortType;
		var fn=function(r1,r2){
			var v1=st(r1.data[f]),v2=st(r2.data[f]);
			if(typeof(v1)=="string"){
				return v1.localeCompare(v2);
			}
			return v1>v2?1:(v1<v2?-1:0);
		};
		this.data.sort(s.direction,fn);
		if(this.snapshot&&this.snapshot!=this.data){
			this.snapshot.sort(s.direction,fn);
		}
	}
}



/*
 * author: xuyan 2009/03/01 初版 06/03 加入Ext.chart.getChartName方法 06/11
 * 加入MSColumn3D, MSColumn3DLineDY 图 06/18
 * 加入Area2D,Bar2D,Bubble,Doughnut2D,Doughnut3D,MSArea,MSBar2D,MSBar3D(共8个) 图
 * 07/01 加入Ext.myutil succeed/failed/unicode/failed四个方法 07/03 加入仪表盘组件 07/05
 * 加入XY散点图 07/24 Ext.myutil加入getBytes方法 --
 * 10/13 重写Ext.Msg.alert， 解决提示信息过短导致的提示框凹陷
 */

Ext.BLANK_IMAGE_URL = basePath + 'ext/resources/images/default/s.gif';
Ext.SSL_SECURE_URL = basePath + 'ext/resources/images/default/s.gif';
// author: xuyan
// 统一编码相关
Ext.tybm = function() {
	var clsCommUrl = basePath + 'JarpListener?className=cn.com.jsepc.midawa.utils.CommUtils';
	var thisMethod = '&methodName=getTybmxx';
	var tybmReader = new Ext.data.JsonReader({}, ['tcode', 'tname']);
	return {
		/*
		 * ----------------------------------------------------------
		 * 统一编码自动获取URL, TreePanle 或者 ComboBox 通过dataUrl加载数据
		 * 只需组织好统一编码查询参数后传入即可,.eg node.loader = new Ext.tree.TreeLoader({
		 * dataUrl: Ext.tybm.getAutoUrl('auto=1&ctid=3&tree=1&async=1') });
		 * ----------------------------------------------------------
		 */
		getAutoUrl : function(params) {
			var paraObj = [Ext.urlDecode(params)];
			var msg = '';
			if (typeof params != 'string') {
				msg += '参数类型错误';
			}
			if (typeof paraObj[0].auto == 'undefined') {
				msg += (msg != '' ? '<br>' : '') + "参数定义错误, 缺少auto参数";
			}
			if (msg != '') {
				Ext.Msg.alert('统一编码 - getAutoUrl', msg, null);
				return '';
			}
			return clsCommUrl + thisMethod + '&paramCount=1&param_0=' + Ext.encode([Ext.urlDecode(params)]);
		},

		/*
		 * ----------------------------------------------------------
		 * 获取统一编码Store的reader,.eg var storeZblb = new Ext.data.Store({
		 * reader:Ext.tybm.getReader() });
		 * ----------------------------------------------------------
		 */
		getReader : function() {
			return tybmReader;
		},

		/*
		 * ---------------------------------------------------------- 获取统一编码,
		 * 传入查询参数以及回调函数, 回调函数接受的参数为http对象 返回的responseText
		 * ----------------------------------------------------------
		 */
		getTheseTybm : function(params, callback) {
			// 验证params以及Http对象
			var msg = '';
			if (typeof params != 'object')
				msg += "参数类型错误, 类型为" + typeof params;
			if (params.length == 0)
				msg += (msg != '' ? '<br>' : '') + "参数长度错误, 长度为0";
			if (msg != '') {
				// alert(msg);
				Ext.Msg.alert('统一编码 - getTheseTybm', msg, null);
				return;
			}
			// 生成参数object
			var pArr = [];
			for (var i = 0; i < params.length; i++) {
				pArr[i] = Ext.urlDecode(params[i]);
			}
			// Send Request
			var thisUrl = clsCommUrl + thisMethod + '&paramCount=0';
			Ext.http.send(thisUrl, function(rtnTxt) {
				callback(Ext.decode(rtnTxt));
			}, Ext.encode(pArr));
		}
	}
}()

// 数据传递相关
Ext.http = function() {
	var httpIndex = 0;
	return {
		/*
		 * ----------------------------------------------------------
		 * 获取http请求对象, 获取失败返回false 方法来源:XMLHttpRequest.js getXMLHttpRequest方法
		 * 包含这个方法可以省去jsp页面include XMLHttpRequest.js 文件, 更加集成化
		 * ----------------------------------------------------------
		 */
		getHttpReqObj : function() {
			var httpReq = "";
			if (window.XMLHttpRequest) {
				httpReq = new XMLHttpRequest();
				if (httpReq.overrideMimeType) {
					httpReq.overrideMimeType("text/xml");
				}
			} else if (window.ActiveXObject) {
				try {
					httpReq = new ActiveXObject("Msxml2.XMLHTTP");
				} catch (e) {
					try {
						httpReq = new ActiveXObject("Microsoft.XMLHTTP");
					} catch (e) {
					}
				}
			}
			if (!httpReq) {
				return false;
			}
			return httpReq;
		},

		/*
		 * ----------------------------------------------------------
		 * 发送请求到后台并在callback中进行返回处理, sendParams是不在url中的参数, 在调用时组织,
		 * json格式的可用Ext.encode(pArr)传入
		 * ----------------------------------------------------------
		 */
		send : function(thisUrl, callback, sendParams) {
			// if(sendParams == null){ //禁止传递null参数
			// Ext.Msg.alert('数据传递 - send', formatMsg('Http参数类型错误, 不能为null值,
			// 请输入字符型'), null);
			// return;
			// }
			if (typeof sendParams == 'undefined') // 不填sendParams参数的情况
				sendParams = null;
			if (sendParams != null && typeof sendParams != 'string') { // 填了sendParams参数,
																		// 要保证类型正确
				Ext.Msg.alert('数据传递 - send', formatMsg('Http参数类型错误, 不能为'
						+ typeof sendParams + '型, 请输入字符型'), null);
				return;
			}
			if (typeof sendParams == 'string' && sendParams.length == 0) {// 填了string型参数,
																			// 要保证参数长度不能为0;
																			// 可以尝试封装object方式,
																			// decode传送
				Ext.Msg.alert('数据传递 - send', formatMsg('Http参数值错误, 长度不能为0'),
						null);
				return;
			}
			var thisIndex = httpIndex++;
			var httpReqName = 'thisHttpReq' + thisIndex;
			var httpCallback = 'thisCallback' + thisIndex;
			var httpReqRtn = 'thisHttpRtn' + thisIndex;

			eval(httpReqName + ' = this.getHttpReqObj();');
			// ---- add these marked lines if validation required ----
			// if(eval(httpReqName + '!=false;')){
			eval(httpCallback + ' = callback');
			eval(httpReqRtn + '=function(){if (' + httpReqName
					+ '.readyState == 4) {if (' + httpReqName
					+ '.status == 200) {' + httpCallback + '(' + httpReqName
					+ '.responseText);' + httpReqName + '=null;}}}');
			// alert(eval(httpReqRtn));
			// 指定http返回处理函数
			eval(httpReqName + '.onreadystatechange = ' + httpReqRtn + ';');
			eval(httpReqName + '.open("POST", thisUrl, true);');
			eval(httpReqName + '.send(sendParams);');
			// }else{
			// Ext.Msg.alert('提示', '获取Http请求对象失败', null);
			// }
		},

		/*
		 * ----------------------------------------------------------
		 * http对象使用情况统计, 叫做pool, 貌似对象池, 其实不是
		 * ----------------------------------------------------------
		 */
		pool : function() {
			var msg = 'there are ' + httpIndex
					+ ' HttpRequest Objects in the pool:';
			for (var i = 0; i < httpIndex; i++) {
				msg += ('<br>' + i + ':') + eval('thisHttpReq' + i);
			}
			Ext.Msg.alert('数据传递 - pool', msg, null);
		}
	}
}()

// Tree操作相关相关
Ext.mytree = function() {
	return {
		/*
		 * ---------------------------------------------------------- 将JSON
		 * Object数据递归填入TreePanel的某一node中
		 * ----------------------------------------------------------
		 */
		fillTree : function(thisNode, theseData) {
			for (var ino = 0; ino < theseData.length; ino++) {
				var newNode = new Ext.tree.TreeNode(theseData[ino]);
				thisNode.appendChild(newNode);
				if (!newNode.isLeaf()) {
					this.fillTree(newNode, theseData[ino].children);
				}
			}
		},

		/*
		 * ----------------------------------------------------------
		 * 删除thisNode节点下的所有子结点, eg.想删除treepanel中根节点下的所有节点
		 * Ext.mytree.clearSubNodes(myTreePnl.getRootNode());
		 * ----------------------------------------------------------
		 */
		clearSubNodes : function(thisNode) {
			var subNodes = thisNode.childNodes;
			for (var i = subNodes.length - 1; i >= 0; i--) {
				subNodes[i].remove();
			}
		},

		/*
		 * ----------------------------------------------------------
		 * 去除树下某个节点下的所有bold信息 selitem 粗体样式 , defined in base.css file .selitem{
		 * font-weight:bold; }
		 * ----------------------------------------------------------
		 */
		resetBoldNodes : function(thisNode) {
			if (typeof thisNode != 'object' || thisNode == null)
				return;
			thisNode.getUI().removeClass('selitem');
			for (var ic = 0; ic < thisNode.childNodes.length; ic++) {
				thisNode.childNodes[ic].getUI().removeClass('selitem');
				if (thisNode.childNodes[ic].childNodes.length > 0)
					this.resetBoldNodes(thisNode.childNodes[ic]);
			}
		}
	}
}()

// fusion charts 操作相关
Ext.chart = function() {
	var swfUrl = {
		column2d : "target/charts/Column2D.swf",
		column3d : "target/charts/Column3D.swf",
		line : "target/charts/Line.swf",
		pie2d : "target/charts/Pie2D.swf",
		pie3d : "target/charts/Pie3D.swf",
		doughnut2d : "target/charts/Doughnut2D.swf",
		doughnut3d : "target/charts/Doughnut3D.swf",
		bar2d : "target/charts/Bar2D.swf",
		msbar2d : "target/charts/MSBar2D.swf",
		msbar3d : "target/charts/MSBar3D.swf",
		stackedcolumn2d : "target/charts/StackedColumn2D.swf",
		stackedcolumn3d : "target/charts/StackedColumn3D.swf",
		stackedbar2d : "target/charts/StackedBar2D.swf",
		stackedbar3d : "target/charts/StackedBar3D.swf",
		area2d : "target/charts/Area2D.swf",
		msarea : "target/charts/MSArea.swf",
		bubble : "target/charts/Bubble.swf",
		mscolumn2d : "target/charts/MSColumn2D.swf",
		mscolumn3d : "target/charts/MSColumn3D.swf",
		mscolumn3dlinedy : "target/charts/MSColumn3DLineDY.swf",
		msline : "target/charts/MSLine.swf",
		radar : "target/charts/Radar.swf",
		angulargauge : "target/charts/AngularGauge.swf", // 仪表盘
		scatter : "target/charts/Scatter.swf"
	};

	// ComboBox中 valueField为value, displayField为text
	var stChart = new Ext.data.SimpleStore({
		fields : ['value', 'text'],
		id : 0,
		data : [['grid', '表格'],
				['Column2D', '2D单维柱状图'],
				['Column3D', '3D单维柱状图'],
				['MSColumn2D', '2D多维柱状图'],
				['MSColumn3D', '3D多维柱状图'],
				['MSColumn3DLineDY', '3D多维双轴图'],
				['Bar2D', '2D单维条形图'],
				['MSBar2D', '2D多维条形图'],
				['MSBar3D', '3D多维条形图'],
				['StackedColumn2D', '2D堆叠柱状图'],
				['StackedColumn3D', '3D堆叠柱状图'],
				['StackedBar2D', '2D堆叠条形图'],
				['StackedBar3D', '3D堆叠条形图'],
				['Line', '单维折线图'],
				['MSLine', '多维折线图'],
				['Area2D', '单维面积图'],
				['MSArea', '多维面积图'],
				['Pie2D', '2D饼图'],
				['Pie3D', '3D饼图'],
				['Doughnut2D', '2D圆环图'],
				['Doughnut3D', '3D圆环图'],
				['Bubble', '气泡图'],
				['Radar', '雷达图'],
				['Scatter', 'XY散点图']]
	});
	return {
		/*
		 * ----------------------------------------------------------
		 * Combox的Store使用Ext.chart.getChartStore valueField 使用 value,
		 * displayField 使用 text
		 * ----------------------------------------------------------
		 */
		getChartStore : function() {
			return stChart;
		},

		/*
		 * ----------------------------------------------------------
		 * 获取根据swf类型获取swf地址, 使用basePath, 可以手工传入bsPath, 如果 没有传入, 使用全局的basePath,
		 * 如果两个值都没有提供, 返回空地址
		 * ----------------------------------------------------------
		 */
		getSwfUrl : function(swfCode, bsPath) {
			if (bsPath == undefined && basePath == undefined) {
				Ext.Msg.alert('图表操作 - getSwfUrl', formatMsg('未提供basePath, 请检查', 2), null);
				return '';
			}
			try {
				eval('swfUrl.' + swfCode.toLowerCase())
			} catch (e) {
				Ext.Msg.alert('图表操作 - getSwfUrl', formatMsg('图形代码' + swfCode + '错误, 请检查', 2), null);
				return '';
			}
			return (bsPath == undefined ? basePath : bsPath) + eval('swfUrl.' + swfCode.toLowerCase());
		},

		/*
		 * ----------------------------------------------------------
		 * 根据传入的chart代码, 返回chart的中文名称
		 * ----------------------------------------------------------
		 */
		getChartName : function(chartcode) {
			var a = null;
			try {
				a = stChart.getById(chartcode).get('text');
			} catch (e) {

			}
			return a;
		}

	/*
	 * ---------------------------------------------------------- 根据选择的swf类型,
	 * 重新加载数据,传入chart所在的panel. 默认param_0携带swf类型值, 作为保留参数
	 * ----------------------------------------------------------
	 */
	// ,loadFlash:function(thisPnl, swfCode){
	// thisPnl.swf = this.getSwfUrl(swfCode);
	// thisPnl.flashvars.dataUrl = setUrlParam(thisPnl.flashvars.dataUrl,
	// 'param_0', swfCode);
	// thisPnl.loadFlash();
	// }
	}
}()

Ext.myutil = function() {
	return {
		/*
		 * ---------------------------------------------------------- 根据传入的r值,
		 * 判断返回值是否成功, 若成功返回true, 否则返回false
		 * ----------------------------------------------------------
		 */
		succeed : function(r) {
			if ('1,s,success'.indexOf(r) > -1) {
				return true;
			}
			return false;
		},
		/*
		 * ---------------------------------------------------------- 根据传入的r值,
		 * 判断返回值是否失败, 若失败返回true, 否则返回false
		 * ----------------------------------------------------------
		 */
		failed : function(r) {
			if ('0,f,fail'.indexOf(r) > -1) {
				return true;
			}
			return false;
		},
		/*
		 * ----------------------------------------------------------
		 * 返回传入字符的unicode编码, \u格式
		 * ----------------------------------------------------------
		 */
		unicode : function(s) {
			var us = '';
			for (i = 0; i < s.length; i++) {
				var c = (s.charCodeAt(i)).toString(16);
				c = "0000".substring(0, 4 - c.length) + c;
				us += "\\u" + c;
			}
			return us;
		},
		/*
		 * ----------------------------------------------------------
		 * 返回传入字符的unicode编码, \u格式, 只转中文字符 如，‘a哈’被转换为‘a\u54c8’
		 * ----------------------------------------------------------
		 */
		cnunicode : function(s) {
			var us = '';
			for (var i = 0; i < s.length; i++) {
				var c = (s.charCodeAt(i)).toString(16);
				if (c.length == 4) {
					us += "\\u" + c;
				} else {
					us += s.charAt(i);
				}
			}
			return us;
		},
		/*
		 * ---------------------------------------------------------- 传入中文信息,
		 * 格式化长度, 第二个参数代表10的倍数 解决alert对话框中字符太短或标题太长导致窗体变形的问题
		 * ----------------------------------------------------------
		 */
		format : function(msg, tens) {
			if (typeof msg != 'string')
				msg = '';
			var slen = 10 * (typeof tens == 'undefined' ? 1 : tens);
			if (msg.length < slen) {
				var len = slen - msg.length;
				for (var i = 0; i < len; i++) {
					msg = ('&nbsp;' + msg + '&nbsp;');
				}
			}
			return msg;
		},
		/*
		 * ----------------------------------------------------------
		 * 传入中文/英文/中英文混合字符, 返回byte数, 中文占2个byte 如:'这个有多长?' 返回11
		 * ----------------------------------------------------------
		 */
		getBytes : function(str) {
			var len = 0;
			for (var i = 0; i < str.length; i++) {
				if (str.charCodeAt(i) > 127 || str.charCodeAt(i) == 94) {
					len += 2;
				} else {
					len++;
				}
			}
			return len;
		},
		/*
		 * ---------------------------------------------------------- 传入字符串,
		 * trim掉前后的空格, trim start and end
		 * ----------------------------------------------------------
		 */
		trimSe : function(str) {
			var rtn;
			try {
				rtn = str.replace(/(^\s*)|(\s*$)/g, "");
			} catch (e) {
				rtn = '';
			}
			return rtn;
		},

		/*
		 * ---------------------------------------------------------- 拷贝函数 参
		 * 数：{Object/Array} o Object or array to clone 返 回 值： {Object/Array}
		 * Deep clone of an object or an array 作 者： Jozef Sakalos
		 * ----------------------------------------------------------
		 */
		clone : function(o) {
			if (!o || 'object' !== typeof o) {
				return o;
			}
			if ('function' === typeof o.clone) {
				return o.clone();
			}
			var c = '[object Array]' === Object.prototype.toString.call(o)
					? []
					: {};
			var p, v;
			for (p in o) {
				if (o.hasOwnProperty(p)) {
					v = o[p];
					if (v && 'object' === typeof v) {
						c[p] = this.clone(v);
					} else {
						c[p] = v;
					}
				}
			}
			return c;
		}
	}
}()

//重写Ext.Msg.alert， 解决提示信息太短导致边框凹陷问题， xuyan@10/13
Ext.Msg.alert = function(X, W, V, U) {
    this.show({
        title: X,
        msg: Ext.myutil.format(W),
        buttons: this.OK,
        fn: V,
        scope: U
    });
    return this
}

// setTimeout(function(){Ext.http.send(basePath +
// 'JarpListener?className=cn.com.jsepc.midawa.utils.CommUtils&methodName=getTybmxx&paramCount=1&param_0=3',
// function(rtnTxt){});}, null);
// setTimeout(function(){po3(Ext.myutil);return;Ext.http.pool();},1000);

// 将字符转为UNICODE编码形式, 反向函数为unescape
function unicodeThis(str) {
	var Code;
	var UnicodeStr = "";
	for (i = 0; i < str.length; i++) {
		Code = (str.charCodeAt(i)).toString(16);
		Code = "0000".substring(0, 4 - Code.length) + Code;
		UnicodeStr += "%u" + Code;
	}
	return UnicodeStr;
}
formatMsg = function(msg, tens) {
	if (typeof msg != 'string')
		msg = '';
	var slen = 10 * (typeof tens == 'undefined' ? 1 : tens);
	if (msg.length < slen) {
		var len = slen - msg.length;
		for (var i = 0; i < len; i++) {
			msg = ('&nbsp;' + msg + '&nbsp;');
		}
	}
	return msg;
}
function po(obj, property, func) {
	// eval(obj.functionname);
	var str = '';
	for (prop in obj) {
		if (typeof(obj[prop]) != 'function') {
			if (property != false) {
				str += prop + ':' + obj[prop] + '\n';
			}
		} else if (func != false) {
			str += prop + ':' + typeof(obj[prop]) + '\n';
		}
	}
	return str;
}
function po2(obj, property, func) {
	if (typeof obj == 'undefined')
		return;
	try {
		var str = '', id = '';
		if (typeof obj == 'object') {
			for (prop in obj) {
				if (typeof(obj[prop]) != 'function') {
					if (property != false) {
						str += prop + ':' + obj[prop] + '\n';
					}
				} else if (func != false) {
					str += prop + ':' + typeof(obj[prop]) + '\n';
				}
			}
			id = 'object:' + (obj.id == undefined ? '' : obj.id);
		} else if (typeof obj == 'string') {
			str = obj;
			id = 'string';
		} else if (typeof obj == 'function') {
			str = eval(obj);
			id = 'function';
		}

		if (typeof Ext != 'undefined') {
			new Ext.Window({
				title : id,
				width : 500,
				height : 350,
				collapsible : true,
				layout : 'fit',
				items : {
					xtype : 'textarea',
					value : str
				}
			}).show();
		} else {
			alert(str);
		}
	} catch (e) {

	}
	// str.replace(/\n/g, '<br/>')
}
var poindex = 0;
function po3(obj, thisid) {
	if (typeof obj == 'undefined') {
		Ext.Msg.alert('po3', formatMsg('object not found'));
		return;
	}
	thisid = thisid == undefined ? 'po3' : thisid;
	try {
		var prestr = '&nbsp;&nbsp;&nbsp;&nbsp;';
		var str = '<br><a style="margin-left:10;">'
				+ formatMsg('<b>PROPERTY</b>', 6).replace(/&nbsp;/g, '-')
				+ '</a><br><br>', strobj = '<br><a style="margin-left:10;">'
				+ formatMsg('<b>OBJECT</b>', 6).replace(/&nbsp;/g, '-')
				+ '</a><br><br>', strfunc = '<br><a style="margin-left:10;">'
				+ formatMsg('<b>FUNCTION</b>', 6).replace(/&nbsp;/g, '-')
				+ '</a><br><br>';
		var bprop = false, bobj = false, bfunc = false;
		if (typeof obj == 'object') {
			for (prop in obj) {
				if (typeof(obj[prop]) == 'object'
						|| typeof(obj[prop]) == 'function') {
					pomethod = 'thisobj' + (poindex++)
					eval(pomethod + '=obj[prop]');
					if (typeof obj[prop] == 'object') {
						bobj = true;
						strobj += '<a style="color:red;margin-left:20;text-decoration:none;font-size:13;" href="javascript:po3(eval(\''
								+ pomethod
								+ '\'),\''
								+ thisid
								+ '.'
								+ prop
								+ '\');">' + prop + '</a><br>';
					} else {
						bfunc = true;
						strfunc += '<a style="color:blue;margin-left:20;text-decoration:none;font-size:13;" href="javascript:po3(eval(\''
								+ pomethod
								+ '\'),\''
								+ thisid
								+ '.'
								+ prop
								+ '\');">' + prop + '</a><br>';
					}
				} else {
					bprop = true;
					str += '<a style="font-size:13;margin-left:20;">' + prop
							+ ':' + obj[prop] + '</a><br>';
				}
			}
			id = thisid + '&nbsp;:&nbsp;<a style="color:red;">' + typeof obj
					+ '</a>';
		} else {
			bprop = true;
			id = thisid + '&nbsp;:&nbsp;' + typeof obj;
			if (typeof obj == 'function') {
				id = thisid + '&nbsp;:&nbsp;<a style="color:blue;">'
						+ typeof obj + '</a>';
				str = '<a style="font-size:12;">'
						+ js_beautify('' + eval(obj), 4, ' ').replace(/\n/g,
								'<br>').replace(/ /g, '&nbsp;') + '</a>';
			} else {
				str = obj;
			}
		}
		new Ext.Window({
			title : id,
			width : 500,
			height : 350,
			collapsible : true,
			maximizable : true,
			layout : 'fit',
			frame : true,
			border : false,
			items : {
				autoScroll : true,
				html : (bprop ? str : '') + (bobj ? strobj : '')
						+ (bfunc ? strfunc : '') + '<br>'
			}
		}).show();
	} catch (e) {

	}
	// str.replace(/\n/g, '<br/>')
}

// var myUrl = basePath +
// 'JarpListener?className=cn.com.jsepc.midawa.utils.CommUtils&methodName=getTybmxx&paramCount=1&param_0=3';
// alert(setUrlParam(myUrl, 'param_0', 'xuyan'));
// 改变url参数中的值
function setUrlParam(thisUrl, key, value) {
	var reg = new RegExp(key + "=[^\\s&#]*", "gi");
	if (reg.test(thisUrl)) {
		thisUrl = thisUrl.replace(reg, key + "=" + value);
	} else {
		thisUrl += "&" + key + "=" + value;
	}
	return thisUrl;
}
var $ = document.getElementById;

// js beautify code, compressed code----
// used in po3 method, for printing function
function js_beautify(js_source_text, indent_size, indent_character,
		indent_level) {
	var input, output, token_text, last_type, last_text, last_word, current_mode, modes, indent_string;
	var whitespace, wordchar, punct, parser_pos, line_starters, in_case;
	var prefix, token_type, do_block_just_closed, var_line, var_line_tainted;
	function trim_output() {
		while (output.length
				&& (output[output.length - 1] === ' ' || output[output.length
						- 1] === indent_string)) {
			output.pop()
		}
	}
	function print_newline(ignore_repeated) {
		ignore_repeated = typeof ignore_repeated === 'undefined'
				? true
				: ignore_repeated;
		trim_output();
		if (!output.length) {
			return
		}
		if (output[output.length - 1] !== "\n" || !ignore_repeated) {
			output.push("\n")
		}
		for (var i = 0; i < indent_level; i++) {
			output.push(indent_string)
		}
	}
	function print_space() {
		var last_output = output.length ? output[output.length - 1] : ' ';
		if (last_output !== ' ' && last_output !== '\n'
				&& last_output !== indent_string) {
			output.push(' ')
		}
	}
	function print_token() {
		output.push(token_text)
	}
	function indent() {
		indent_level++
	}
	function unindent() {
		if (indent_level) {
			indent_level--
		}
	}
	function remove_indent() {
		if (output.length && output[output.length - 1] === indent_string) {
			output.pop()
		}
	}
	function set_mode(mode) {
		modes.push(current_mode);
		current_mode = mode
	}
	function restore_mode() {
		do_block_just_closed = current_mode === 'DO_BLOCK';
		current_mode = modes.pop()
	}
	function in_array(what, arr) {
		for (var i = 0; i < arr.length; i++) {
			if (arr[i] === what) {
				return true
			}
		}
		return false
	}
	function get_next_token() {
		var n_newlines = 0;
		var c = '';
		do {
			if (parser_pos >= input.length) {
				return ['', 'TK_EOF']
			}
			c = input.charAt(parser_pos);
			parser_pos += 1;
			if (c === "\n") {
				n_newlines += 1
			}
		} while (in_array(c, whitespace));
		if (n_newlines > 1) {
			for (var i = 0; i < 2; i++) {
				print_newline(i === 0)
			}
		}
		var wanted_newline = (n_newlines === 1);
		if (in_array(c, wordchar)) {
			if (parser_pos < input.length) {
				while (in_array(input.charAt(parser_pos), wordchar)) {
					c += input.charAt(parser_pos);
					parser_pos += 1;
					if (parser_pos === input.length) {
						break
					}
				}
			}
			if (parser_pos !== input.length && c.match(/^[0-9]+[Ee]$/)
					&& input.charAt(parser_pos) === '-') {
				parser_pos += 1;
				var t = get_next_token(parser_pos);
				c += '-' + t[0];
				return [c, 'TK_WORD']
			}
			if (c === 'in') {
				return [c, 'TK_OPERATOR']
			}
			return [c, 'TK_WORD']
		}
		if (c === '(' || c === '[') {
			return [c, 'TK_START_EXPR']
		}
		if (c === ')' || c === ']') {
			return [c, 'TK_END_EXPR']
		}
		if (c === '{') {
			return [c, 'TK_START_BLOCK']
		}
		if (c === '}') {
			return [c, 'TK_END_BLOCK']
		}
		if (c === ';') {
			return [c, 'TK_END_COMMAND']
		}
		if (c === '/') {
			var comment = '';
			if (input.charAt(parser_pos) === '*') {
				parser_pos += 1;
				if (parser_pos < input.length) {
					while (!(input.charAt(parser_pos) === '*'
							&& input.charAt(parser_pos + 1) && input
							.charAt(parser_pos + 1) === '/')
							&& parser_pos < input.length) {
						comment += input.charAt(parser_pos);
						parser_pos += 1;
						if (parser_pos >= input.length) {
							break
						}
					}
				}
				parser_pos += 2;
				return ['/*' + comment + '*/', 'TK_BLOCK_COMMENT']
			}
			if (input.charAt(parser_pos) === '/') {
				comment = c;
				while (input.charAt(parser_pos) !== "\x0d"
						&& input.charAt(parser_pos) !== "\x0a") {
					comment += input.charAt(parser_pos);
					parser_pos += 1;
					if (parser_pos >= input.length) {
						break
					}
				}
				parser_pos += 1;
				if (wanted_newline) {
					print_newline()
				}
				return [comment, 'TK_COMMENT']
			}
		}
		if (c === "'"
				|| c === '"'
				|| (c === '/' && ((last_type === 'TK_WORD' && last_text === 'return') || (last_type === 'TK_START_EXPR'
						|| last_type === 'TK_END_BLOCK'
						|| last_type === 'TK_OPERATOR'
						|| last_type === 'TK_EOF' || last_type === 'TK_END_COMMAND')))) {
			var sep = c;
			var esc = false;
			c = '';
			if (parser_pos < input.length) {
				while (esc || input.charAt(parser_pos) !== sep) {
					c += input.charAt(parser_pos);
					if (!esc) {
						esc = input.charAt(parser_pos) === '\\'
					} else {
						esc = false
					}
					parser_pos += 1;
					if (parser_pos >= input.length) {
						break
					}
				}
			}
			parser_pos += 1;
			if (last_type === 'TK_END_COMMAND') {
				print_newline()
			}
			return [sep + c + sep, 'TK_STRING']
		}
		if (in_array(c, punct)) {
			while (parser_pos < input.length
					&& in_array(c + input.charAt(parser_pos), punct)) {
				c += input.charAt(parser_pos);
				parser_pos += 1;
				if (parser_pos >= input.length) {
					break
				}
			}
			return [c, 'TK_OPERATOR']
		}
		return [c, 'TK_UNKNOWN']
	}
	indent_character = indent_character || ' ';
	indent_size = indent_size || 4;
	indent_string = '';
	while (indent_size--) {
		indent_string += indent_character
	}
	input = js_source_text;
	last_word = '';
	last_type = 'TK_START_EXPR';
	last_text = '';
	output = [];
	do_block_just_closed = false;
	var_line = false;
	var_line_tainted = false;
	whitespace = "\n\r\t ".split('');
	wordchar = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$'
			.split('');
	punct = '+ - * / % & ++ -- = += -= *= /= %= == === != !== > < >= <= >> << >>> >>>= >>= <<= && &= | || ! !! , : ? ^ ^= |='
			.split(' ');
	line_starters = 'continue,try,throw,return,var,if,switch,case,default,for,while,break,function'
			.split(',');
	current_mode = 'BLOCK';
	modes = [current_mode];
	indent_level = indent_level || 0;
	parser_pos = 0;
	in_case = false;
	while (true) {
		var t = get_next_token(parser_pos);
		token_text = t[0];
		token_type = t[1];
		if (token_type === 'TK_EOF') {
			break
		}
		switch (token_type) {
			case 'TK_START_EXPR' :
				var_line = false;
				set_mode('EXPRESSION');
				if (last_type === 'TK_END_EXPR'
						|| last_type === 'TK_START_EXPR') {
				} else if (last_type !== 'TK_WORD'
						&& last_type !== 'TK_OPERATOR') {
					print_space()
				} else if (in_array(last_word, line_starters)
						&& last_word !== 'function') {
					print_space()
				}
				print_token();
				break;
			case 'TK_END_EXPR' :
				print_token();
				restore_mode();
				break;
			case 'TK_START_BLOCK' :
				if (last_word === 'do') {
					set_mode('DO_BLOCK')
				} else {
					set_mode('BLOCK')
				}
				if (last_type !== 'TK_OPERATOR'
						&& last_type !== 'TK_START_EXPR') {
					if (last_type === 'TK_START_BLOCK') {
						print_newline()
					} else {
						print_space()
					}
				}
				print_token();
				indent();
				break;
			case 'TK_END_BLOCK' :
				if (last_type === 'TK_START_BLOCK') {
					trim_output();
					unindent()
				} else {
					unindent();
					print_newline()
				}
				print_token();
				restore_mode();
				break;
			case 'TK_WORD' :
				if (do_block_just_closed) {
					print_space();
					print_token();
					print_space();
					break
				}
				if (token_text === 'case' || token_text === 'default') {
					if (last_text === ':') {
						remove_indent()
					} else {
						unindent();
						print_newline();
						indent()
					}
					print_token();
					in_case = true;
					break
				}
				prefix = 'NONE';
				if (last_type === 'TK_END_BLOCK') {
					if (!in_array(token_text.toLowerCase(), ['else', 'catch',
							'finally'])) {
						prefix = 'NEWLINE'
					} else {
						prefix = 'SPACE';
						print_space()
					}
				} else if (last_type === 'TK_END_COMMAND'
						&& (current_mode === 'BLOCK' || current_mode === 'DO_BLOCK')) {
					prefix = 'NEWLINE'
				} else if (last_type === 'TK_END_COMMAND'
						&& current_mode === 'EXPRESSION') {
					prefix = 'SPACE'
				} else if (last_type === 'TK_WORD') {
					prefix = 'SPACE'
				} else if (last_type === 'TK_START_BLOCK') {
					prefix = 'NEWLINE'
				} else if (last_type === 'TK_END_EXPR') {
					print_space();
					prefix = 'NEWLINE'
				}
				if (last_type !== 'TK_END_BLOCK'
						&& in_array(token_text.toLowerCase(), ['else', 'catch',
								'finally'])) {
					print_newline()
				} else if (in_array(token_text, line_starters)
						|| prefix === 'NEWLINE') {
					if (last_text === 'else') {
						print_space()
					} else if ((last_type === 'TK_START_EXPR' || last_text === '=')
							&& token_text === 'function') {
					} else if (last_type === 'TK_WORD'
							&& (last_text === 'return' || last_text === 'throw')) {
						print_space()
					} else if (last_type !== 'TK_END_EXPR') {
						if ((last_type !== 'TK_START_EXPR' || token_text !== 'var')
								&& last_text !== ':') {
							if (token_text === 'if' && last_type === 'TK_WORD'
									&& last_word === 'else') {
								print_space()
							} else {
								print_newline()
							}
						}
					} else {
						if (in_array(token_text, line_starters)
								&& last_text !== ')') {
							print_newline()
						}
					}
				} else if (prefix === 'SPACE') {
					print_space()
				}
				print_token();
				last_word = token_text;
				if (token_text === 'var') {
					var_line = true;
					var_line_tainted = false
				}
				break;
			case 'TK_END_COMMAND' :
				print_token();
				var_line = false;
				break;
			case 'TK_STRING' :
				if (last_type === 'TK_START_BLOCK'
						|| last_type === 'TK_END_BLOCK') {
					print_newline()
				} else if (last_type === 'TK_WORD') {
					print_space()
				}
				print_token();
				break;
			case 'TK_OPERATOR' :
				var start_delim = true;
				var end_delim = true;
				if (var_line && token_text !== ',') {
					var_line_tainted = true;
					if (token_text === ':') {
						var_line = false
					}
				}
				if (token_text === ':' && in_case) {
					print_token();
					print_newline();
					break
				}
				in_case = false;
				if (token_text === ',') {
					if (var_line) {
						if (var_line_tainted) {
							print_token();
							print_newline();
							var_line_tainted = false
						} else {
							print_token();
							print_space()
						}
					} else if (last_type === 'TK_END_BLOCK') {
						print_token();
						print_newline()
					} else {
						if (current_mode === 'BLOCK') {
							print_token();
							print_newline()
						} else {
							print_token();
							print_space()
						}
					}
					break
				} else if (token_text === '--' || token_text === '++') {
					if (last_text === ';') {
						start_delim = true;
						end_delim = false
					} else {
						start_delim = false;
						end_delim = false
					}
				} else if (token_text === '!' && last_type === 'TK_START_EXPR') {
					start_delim = false;
					end_delim = false
				} else if (last_type === 'TK_OPERATOR') {
					start_delim = false;
					end_delim = false
				} else if (last_type === 'TK_END_EXPR') {
					start_delim = true;
					end_delim = true
				} else if (token_text === '.') {
					start_delim = false;
					end_delim = false
				} else if (token_text === ':') {
					if (last_text.match(/^\d+$/)) {
						start_delim = true
					} else {
						start_delim = false
					}
				}
				if (start_delim) {
					print_space()
				}
				print_token();
				if (end_delim) {
					print_space()
				}
				break;
			case 'TK_BLOCK_COMMENT' :
				print_newline();
				print_token();
				print_newline();
				break;
			case 'TK_COMMENT' :
				print_space();
				print_token();
				print_newline();
				break;
			case 'TK_UNKNOWN' :
				print_token();
				break
		}
		last_type = token_type;
		last_text = token_text
	}
	return output.join('')
}





